use chrono::Local;
use local_ip_address::{list_afinet_netifas, local_ip};
use std::error::Error;
mod aliapi;
use aliapi::Aliapi;
use structopt::StructOpt;

fn main() -> Result<(), Box<dyn Error>> {
    let args = CommandArgs::from_args();

    let domain_name = &args.domain;
    let rr = &args.host;
    let aliapi = Aliapi::new(&args.access_key, &args.secret_key);

    let rsp = aliapi.domain_records(domain_name, rr)?;
    let mut current_ip = String::new();

    let records = rsp["DomainRecords"]["Record"].clone();
    if records.as_array().unwrap().len() <= 0 {
        println!("domain {}.{} is not exist.", rr, domain_name);
        return Ok(());
    }

    let record = rsp["DomainRecords"]["Record"][0].clone();
    let record_type = record["Type"].as_str().unwrap();
    let record_id = record["RecordId"].as_str().unwrap();
    let old_ip = record["Value"].as_str().unwrap();

    let ip_name;
    if record_type.eq("AAAA") {
        ip_name = "IPv6";
        let rst = list_afinet_netifas()?;
        // println!("{:?}", rst.clone());
        for (_, ip) in rst {
            if ip.is_loopback() {
                continue;
            }
            if !ip.to_string().to_lowercase().starts_with("fe80") {
                current_ip = ip.to_string();
            }
        }
    } else if record_type.eq("A") {
        ip_name = "IPv4";
        current_ip = local_ip().unwrap().to_string();
    } else {
        println!("Record type [{}] is not supported", record_type);
        return Ok(());
    }

    let timestamp = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
    println!("[{}] Local {ip_name} is {}", timestamp, current_ip.clone());
    println!(
        "[{}] RecordId: {}, {ip_name}: {}",
        timestamp, record_id, old_ip
    );
    if old_ip.eq(current_ip.as_str()) {
        println!(
            "[{}] The {ip_name} address [{}] is not changed and ignored.",
            timestamp, current_ip
        )
    } else if current_ip.is_empty() {
        println!(
            "[{}] The {ip_name} address is empty and ignored.",
            timestamp
        )
    } else {
        println!(
            "[{}] The local {ip_name} address has been changed to {}",
            timestamp, current_ip
        );

        aliapi.update_domain_record(record_id, &current_ip, rr, record_type)?;
        println!(
            "[{}] Domain {}.{} has been updated to {}",
            timestamp,
            rr,
            domain_name,
            current_ip.clone()
        );
    }

    Ok(())
}

/// 基于阿里云API实现的DDNS客户端。
/// 在使用该程序前，请在阿里云的“控制台 -> 云解析DNS”功能中将对应的域名添加进去。
#[derive(StructOpt, Debug)]
#[structopt(name = "aliddns")]
struct CommandArgs {
    /// 访问阿里云的 access_key
    #[structopt(short, long)]
    access_key: String,

    /// 访问阿里云的 secret_key
    #[structopt(short, long)]
    secret_key: String,

    /// 域名
    #[structopt(short, long)]
    domain: String,

    /// 主机名，二级域名
    #[structopt(short, long)]
    host: String,
}
